package com.ai.networking.netty.handler;

import com.ai.config.SpringContext;
import com.ai.entity.comm.SysNetty;
import com.ai.entity.network.*;
import com.ai.networking.netty.comm.CommonNetty;
import com.ai.service.made.*;
import com.ai.service.networking.ISysNettyService;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;


/**
 * 当客户端建立起与服务端的连接后，客户端有什么动作，下面方法均有体验
 * @author zzy
 */
@Slf4j
public class ServerHandler extends ChannelInboundHandlerAdapter {

    private SysNetty nettyServer;

    ISysNettyService sysNettyService;

    private IL1SignalService il1SignalService;

    private IL2SignalService il2SignalService;

    private IAGSignalService iAGSignalService;

    private ISISignalService isISignalService;

    public ServerHandler() {
    }

    public ServerHandler(String ip, int port) {
        sysNettyService = SpringContext.getBean(ISysNettyService.class);
        il1SignalService=SpringContext.getBean(IL1SignalService.class);
        il2SignalService=SpringContext.getBean(IL2SignalService.class);
        iAGSignalService=SpringContext.getBean(IAGSignalService.class);
        isISignalService=SpringContext.getBean(ISISignalService.class);
        nettyServer = sysNettyService.getByIP(ip, port);
    }

    /**
     * channelAction
     * channel 通道 action 活跃的
     * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     * 有客户端连接时，首先会触发Inbound处理器的注册以及激活工作，
     * 激活完成之后，就可以实现实现客户端与服务端消息的收发功能了
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String clientCode = "";
        if (nettyServer!=null){
            clientCode = nettyServer.getCode();
        }
        log.info("=========客户端：{} 建立了一个新连接=========",clientCode);
        /**
         * 记录每一个信道----》服务端想要给客户端发送消息，就需要获取客户端对应的信道
         * 不同的客户端，对应的端口号不同，  通过端口号  定位到 信道，  从而获取到指定的客户端
         */
        CommonNetty.ctxMap.put(clientCode, ctx);
        super.channelActive(ctx);
    }

    /**
     * channelInactive
     * channel 通道 Inactive 不活跃的
     * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     *
     * @param ctx
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String clientCode = nettyServer.getCode();
        log.error("=========客户端：{} 断开了连接=========",clientCode);
        CommonNetty.ctxMap.remove(clientCode);
        super.channelInactive(ctx);
    }

    /**
     *  读取客户端发送来的消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 处理不同类型的消息
        if (msg instanceof HeartMessage) {
//            log.info("  ========================  开始处理发送的心跳信号  ========================");
            //收到的为心跳电文，  给信道标记收到心跳的时间------最后一次读写时间
//            ctx.channel().attr(AttributeKey.valueOf(Constants.ReadTime))
//                    .set(System.currentTimeMillis());
        }else if (msg instanceof AgToDsSysMessage) {
            AgToDsSysMessage agToDsSysMessage = (AgToDsSysMessage) msg;
            log.info("  ========================  开始处理AG发送的操作信号  ========================");
            iAGSignalService.receiveSignal(agToDsSysMessage);
        } else if (msg instanceof L1ToDsSysMessage) {
            L1ToDsSysMessage l1ToDsSysMessage = (L1ToDsSysMessage) msg;
            log.info("  ========================  开始处理L1发送的操作信号  ========================");
            il1SignalService.receiveSignal(l1ToDsSysMessage);
        } else if (msg instanceof SiToDsSysMessage) {
            SiToDsSysMessage siToDsSysMessage = (SiToDsSysMessage) msg;
            log.info("  ========================  开始处理SI发送的操作信号  ========================");
            isISignalService.receiveSignal(siToDsSysMessage);
        } else if (msg instanceof L2ToDsSysMessage) {
            L2ToDsSysMessage l2ToDsSysMessage = (L2ToDsSysMessage) msg;
            log.info("  ========================  开始处理L2发送的操作信号  ========================");
            il2SignalService.receiveSignal(l2ToDsSysMessage);
        }
    }

    /**
     * 客户端消息读取完毕
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }
    
    /**
     *  发生了异常
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("--------Netty Exception ExceptionCaught : 【" + nettyServer.getCode() + "】 : "
                + cause.getMessage() + "=======================", cause);
        ctx.flush();
        ctx.close();
    }
}
